package com.gitee.wsl.compose.ui.richtext.edit.model.paragraph.type.list

import androidx.compose.ui.text.ParagraphStyle
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.style.TextIndent
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.sp
import com.gitee.wsl.compose.ui.richtext.edit.annotation.ExperimentalRichTextApi
import com.gitee.wsl.compose.ui.richtext.edit.model.DefaultListIndent
import com.gitee.wsl.compose.ui.richtext.edit.model.DefaultOrderedListStyleType
import com.gitee.wsl.compose.ui.richtext.edit.model.span.RichSpan
import com.gitee.wsl.compose.ui.richtext.edit.model.RichTextConfig
import com.gitee.wsl.compose.ui.richtext.edit.model.paragraph.RichParagraph
import com.gitee.wsl.compose.ui.richtext.edit.model.paragraph.type.ParagraphType
import com.gitee.wsl.reflect.prop


class OrderedList private constructor(
    number: Int,
    initialIndent: Int = DefaultListIndent,
    startTextWidth: TextUnit = 0.sp,
    initialLevel: Int = 1,
    initialStyleType: OrderedListStyleType = DefaultOrderedListStyleType,
) : AbstractList(initialIndent,  startTextWidth, initialLevel) {

    constructor(
        number: Int,
        initialLevel: Int = 1,
    ) : this(
        number = number,
        initialIndent = DefaultListIndent,
        initialLevel = initialLevel,
    )

    constructor(
        number: Int,
        config: RichTextConfig,
        startTextWidth: TextUnit = 0.sp,
        initialLevel: Int = 1,
    ) : this(
        number = number,
        initialIndent = config.orderedListIndent,
        startTextWidth = startTextWidth,
        initialLevel = initialLevel,
        initialStyleType = config.orderedListStyleType,
    )

//    var number = number
//        set(value) {
//            field = value
//            startRichSpan = getNewStartRichSpan(startRichSpan.textRange)
//        }

    var number:Int by prop(number){
        startRichSpan = getNewStartRichSpan(startRichSpan.textRange)
    }

    private var styleType: OrderedListStyleType = initialStyleType
        set(value) {
            field = value
            startRichSpan = getNewStartRichSpan(startRichSpan.textRange)
        }

    override fun getStyle(config: RichTextConfig): ParagraphStyle {
        if (config.orderedListIndent != indent) {
            indent = config.orderedListIndent
        }

        if (config.orderedListStyleType != styleType) {
            styleType = config.orderedListStyleType
        }

        return style
    }

    override fun getNewParagraphStyle() =
        ParagraphStyle(
            textIndent = TextIndent(
                firstLine = ((indent * level) - startTextWidth.value).sp,
                restLine = (indent * level).sp
            )
        )

    @OptIn(ExperimentalRichTextApi::class)
    override fun getNewStartRichSpan(textRange: TextRange): RichSpan {
        val text = styleType.format(number, level) + styleType.getSuffix(level)

        return RichSpan(
            paragraph = RichParagraph(type = this),
            text = text,
            textRange = TextRange(
                textRange.min,
                textRange.min + text.length
            )
        )
    }

    override fun getNextParagraphType(): ParagraphType =
        OrderedList(
            number = number + 1,
            initialIndent = indent,
            startTextWidth = startTextWidth,
            initialLevel = level,
            initialStyleType = styleType,
        )

    override fun copy(): ParagraphType =
        OrderedList(
            number = number,
            initialIndent = indent,
            startTextWidth = startTextWidth,
            initialLevel = level,
            initialStyleType = styleType,
        )

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is OrderedList) return false

        if (number != other.number) return false
        if (indent != other.indent) return false
        if (startTextWidth != other.startTextWidth) return false
        if (level != other.level) return false
        if (styleType != other.styleType) return false

        return true
    }

    override fun hashCode(): Int {
        var result = indent
        result = 31 * result + number
        result = 31 * result + indent
        result = 31 * result + startTextWidth.hashCode()
        result = 31 * result + level
        result = 31 * result + styleType.hashCode()
        return result
    }
}


fun ParagraphType.orderedList(number: Int,
                              config: RichTextConfig,
                              startTextWidth: TextUnit = 0.sp,
                              initialLevel: Int = 1,
) = OrderedList(
    number = number,
    config = config,
    startTextWidth = startTextWidth,
    initialLevel = initialLevel,
)

fun ParagraphType.orderedList(number: Int,
                              initialLevel: Int = 1,
) = OrderedList(
    number = number,
    initialLevel = initialLevel,
)